package futbol.tacticas.concursantes.V3rgu1;


import futbol.General;
import futbol.tacticas.*;
import futbol.tacticas.concursantes.Tactica;
import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * Clase Base de Configuración de datos claves del partido.
 * 
 * @author jose
 */
class Configuracion {
    private int numPorteros = 1;
    private int pxMarcajeDefensa = 10;
    private int pxMarcajeAtaque = 20;
    private int pxDistanciaPaseLargo = 50;

    public int getNumPorteros() {
        return numPorteros;
    }

    public void setNumPorteros(int numPorteros) {
        this.numPorteros = numPorteros;
    }

    public int getPxMarcajeDefensa() {
        return pxMarcajeDefensa;
    }

    public void setPxMarcajeDefensa(int pxMarcajeDefensa) {
        this.pxMarcajeDefensa = pxMarcajeDefensa;
    }

    public int getPxMarcajeAtaque() {
        return pxMarcajeAtaque;
    }

    public void setPxMarcajeAtaque(int pxMarcajeAtaque) {
        this.pxMarcajeAtaque = pxMarcajeAtaque;
    }

    public int getPxDistanciaPaseLargo() {
        return pxDistanciaPaseLargo;
    }

    public void setPxDistanciaPaseLargo(int pxDistanciaPaseLargo) {
        this.pxDistanciaPaseLargo = pxDistanciaPaseLargo;
    }
}

/**
 * Clase que implementa la interfaz Tactica.
 * 
 * @author jose
 */
public class V3rgu1 implements Tactica {

    private Configuracion config;
    private static final Point REFERENCIA_PORTERO = new Point(-160, 0);

    public interface Tacticas {

        /** 4-4-2 */
        public static final int CLASICA[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {10, 20}, // Pivote diestro 6
            {10, -20}, // Pivote zurdo 7
            {25, 75}, // Interior diestro 8
            {25, -75}, // Interior zurdo 9

            {100, -30}, // Delantero Centro diestro [10]
            {100, 30}, // Delantero Centro zurdo [11]  
                                                                                                            };
        
        /** 4-2-3-1 */
        public static final int DEL_BOSQUE[][] = {
            {-145, 0}, // Portero [1]

            {-75, 50}, // Lateral Derecho [2]
            {-75, -50}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-20, -30}, // Doble Pivote (D) [6]
            {-20, 30}, // Doble Pivote (I) [7]

            {25, 75}, // Extremo Derecho [8]
            {100, 0}, // Delantero Centro [9]
            {50, 0}, // Mediapunta [10]
            {25, -75} // Extremo Derecho [11]
        };
        /** 4-4-2 en rombo */
        public static final int ROMBO[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-25, 0}, // Pivote diestro 6
            {50, 0}, // Pivote zurdo 7
            {15, 75}, // Interior diestro 8
            {15, -75}, // Interior zurdo 9

            {100, -30}, // Delantero Centro diestro [10]
            {100, 30}, // Delantero Centro zurdo [11]
                                                                                                            };
        
        /** 4-3-3 */
        public static final int CRUYFF[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-25, 0}, // Organizador 6
            {0, 65}, // Interior zurdo 7
            {0, -65}, // Interior diestro 8

            {100, 0}, // Delantero centro 9            
            {90, -65}, // Extremo diestro [10]
            {90, 65}, // Extremo zurdo [11]  
                                                                                                            };
        
        /** 4-2-4 */
        public static final int BRASIL[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-25, -35}, // Organizador diestro 6
            {-25, 35}, // Organizador zurdo 7

            {90, -30}, // Delantero diestro 8            
            {90, 30}, // Delantero zurdo 9            
            {80, -65}, // Extremo diestro [10]
            {80, 65}, // Extremo zurdo [11]  
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-50, 0}, // Organizador 6

            {-20, -35}, // Organizador diestro 6
            {-20, 35}, // Organizador zurdo 7

            {60, -30}, // Delantero diestro 8            
            {60, 30}, // Delantero zurdo 9

            {100, 0}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY2[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-40, 0}, // Organizador 6

            {0, -35}, // Organizador diestro 6
            {0, 35}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {120, -30}, // Delantero Centro [11]
            {120, +30}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY3[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-40, -35}, // Organizador 6
            {-40, 35}, // Organizador 6

            {0, -50}, // Organizador diestro 6
            {0, +50}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {120, -30}, // Delantero Centro [11]
            {120, +30}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY4[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-40, -35}, // Organizador 6
            {-40, 35}, // Organizador 6

            {0, -50}, // Organizador diestro 6
            {0, +50}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {120, -75}, // Delantero Centro [11]
            {120, +75}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY5[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-100, 20}, // Central Derecho [4]
            {-100, -20}, // Central Izquierdo [5]

            {-40, -35}, // Organizador 6
            {-40, 35}, // Organizador 6

            {0, -40}, // Organizador diestro 6
            {10, +40}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {120, -40}, // Delantero Centro [11]
            {120, +40}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-1-2-2-1 */
        public static final int UNAY6[][] = {
            {-145, 0}, // Portero [1]

            {-75, 75}, // Lateral Derecho [2]
            {-75, -75}, // Lateral Izquierdo [3]
            {-80, 20}, // Central Derecho [4]
            {-80, -20}, // Central Izquierdo [5]

            {-30, -35}, // Organizador 6
            {-30, 35}, // Organizador 6

            {15, -40}, // Organizador diestro 6
            {15, +40}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {110, -40}, // Delantero Centro [11]
            {110, +40}, // Delantero Centro [11]
                                                                                                            };
        
        /** 4-2-2-1-2 */
        /** 3-3-2-1-2 */
        public static final int UNAY7[][] = {
            {-145, 0}, // Portero [1]

            {-75, 50},
            {-80, 0},
            {-75, -50},
            {-30, 50},
            {-35, 0},
            {-30, -50},

            {-30, -35}, // Organizador 6
            {-30, 35}, // Organizador 6

            {15, -40}, // Organizador diestro 6
            {15, +40}, // Organizador zurdo 7

            {75, 0}, // Delantero diestro 8            

            {110, -40}, // Delantero Centro [11]
            {110, +40}, // Delantero Centro [11]
                                                                                                            };
        
        /** 5-3-2 */
        public static final int CARRILEROS_DEFENDIENDO[][] = {
            {-145, 0}, // Portero [1]

            {-75, 85}, // Lateral Derecho [2]
            {-75, -85}, // Lateral Izquierdo [3]
            {-100, 40}, // Central Derecho [4]
            {-100, -40}, // Central Izquierdo [5]
            {-75, 0}, // Libero 6

            {25, 0}, // Organizador 7
            {0, 65}, // Interior zurdo 8
            {0, -65}, // Interior diestro 9

            {100, -30}, // Delantero Centro diestro [10]
            {100, 30}, // Delantero Centro zurdo [11]
                                                                                                            };
        
        /** 3-4-1-2 */
        public static final int CARRILEROS_ATACANDO[][] = {
            {-145, 0}, // Portero [1]

            {-90, 50}, // Central Derecho [2]
            {-90, -50}, // Central Izquierdo [3]
            {-90, 0}, // Libero [4]

            {-15, 85}, // Carrilero Derecho [5]
            {-15, -85}, // Carrilero Izquierdo [6]
            {0, 30}, // Interior zurdo [7]
            {0, -30}, // Interior diestro [8]

            {50, 0}, // Media punta [9]

            {100, -30}, // Delantero Centro diestro [10]
            {100, 30}, // Delantero Centro zurdo [11]
                    }
        ;
        
        /** 5-4-1 */
        public static final int CLEMENTE[][] = {
            {-145, 0}, // Portero [1]

            {-75, 85}, // Lateral Derecho [2]
            {-75, -85}, // Lateral Izquierdo [3]
            {-100, 40}, // Central Derecho [4]
            {-100, -40}, // Central Izquierdo [5]
            {-75, 0}, // Libero 6

            {25, 30}, // Organizador Derecho [7]
            {25, -30}, // Organizador Izquiero [8]
            {0, 75}, // Interior zurdo 9
            {0, -75}, // Interior diestro 10

            {100, 0}, // Delantero Centro [11]
    }
        ;
        
    }//interface
            
    
    
    
    
    private Point bolaAnterior = null;
    private Point bolaFutura = null;
    private Point bola = null;
    private double velocidadAnterior;
    private double velocidadActual;
    // Fuerzas flojas
    //private int nFuerzas[] = {5, 3, 3, 4, 4, 3, 4, 5, 7, 6, 5};
    //private int nFuerzas[] = {6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
    // Super fuerzas
    //private int nFuerzas[] = {6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
    private int nFuerzas[] = {6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7};
    //private int nFuerzas[] = {6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7};

    public int TACTICA_ACTUAL[][];
    public int golpes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    public Point zonas[] = {
        new Point(40, -120),
        new Point(40, 400),
        new Point(40, -75),
        new Point(40, -50),
        new Point(40, -25),
        new Point(40, 0),
        new Point(40, +25),
        new Point(40, +50),
        new Point(40, +75),
        new Point(40, +100),
        new Point(40, +120),
        new Point(80, -120),
        new Point(80, 800),
        new Point(80, -75),
        new Point(80, -50),
        new Point(80, -25),
        new Point(80, 0),
        new Point(80, +25),
        new Point(80, +50),
        new Point(80, +75),
        new Point(80, +100),
        new Point(80, +120),
        new Point(120, -120),
        new Point(120, 1200),
        new Point(120, -75),
        new Point(120, -50),
        new Point(120, -25),
        new Point(120, 0),
        new Point(120, +25),
        new Point(120, +50),
        new Point(120, +75),
        new Point(120, +100),
        new Point(120, +120),
        new Point(160, -120),
        new Point(160, 1600),
        new Point(160, -75),
        new Point(160, -50),
        new Point(160, -25),
        new Point(160, 0),
        new Point(160, +25),
        new Point(160, +50),
        new Point(160, +75),
        new Point(160, +100),
        new Point(160, +120)
        }; 

    public V3rgu1() {
        this.TACTICA_ACTUAL = Tacticas.UNAY6;

        this.config = new Configuracion();
        this.config.setPxMarcajeDefensa(25);
        this.config.setPxMarcajeAtaque(25);
        this.config.setNumPorteros(1);
        this.config.setPxDistanciaPaseLargo(50);
    }

    public String getNombre() {
        return "c.d. v3rgu1";
    }

    public Color getColor1(){
        return Color.BLUE;
    }
    
    public Color getColor2(){
        return Color.BLACK;
    }
    
    public Color getColorNumero(){
        return Color.CYAN;
    }
    
//    public Color getColor1() {
//        return Color.ORANGE;
//    }
//
//    public Color getColor2() {
//        return Color.BLACK;
//    }
//
//    public Color getColorNumero() {
//        return Color.WHITE;
//    }

    public int getFuerza(int n) {
        return nFuerzas[n];
    }

    public int getVelocidad(int n) {
        return 10 - nFuerzas[n];
    }

    public int getXInicial(int n) {
        return this.TACTICA_ACTUAL[n][0];
    }

    public int getYInicial(int n) {
        return this.TACTICA_ACTUAL[n][1];
    }

    public Vector<Comando> getComandos(SituacionJugadores sj) {
        Vector<Comando> comandos = new Vector();

        this.bola = sj.getBola();

        int ultimaDistanciaRecorrida = (this.bolaAnterior != null) ? (int) General.getDistancia(this.bolaAnterior.x, this.bolaAnterior.y, this.bola.x, this.bola.y) : 0;

        this.velocidadAnterior = this.velocidadActual;
        this.velocidadActual = ultimaDistanciaRecorrida;

        this.bolaFutura = posibleFuturaPosicionBola2(sj);

        if (this.bolaAnterior == null) {
            this.posicionarJugadoresNuevo(sj, comandos);
        }

        this.porterearBasico(sj, comandos);

        this.jugar(sj, comandos);

        this.bolaAnterior = this.bola;

        return comandos;
    }

    /**
     * Posiciona cada jugador en su lugar según la táctica actual.
     */
    private void posicionarJugadoresNuevo(SituacionJugadores sj, Vector<Comando> comandos) {

        if (this.TACTICA_ACTUAL == null) {
            this.cambiarTactica(Tacticas.CLASICA);
        }

        for (int n = 10; n >= this.config.getNumPorteros(); n--) {
            comandos.add(new ComandoIrA(n, this.TACTICA_ACTUAL[n][0], this.TACTICA_ACTUAL[n][1]));
        }
    }

    /**
     * Gestiona los movimientos del portero.
     * 
     * @param sj
     * @param comandos
     */
    private void porterearBasico(SituacionJugadores sj, Vector<Comando> comandos) {

        // --------------------------------------------------------------
        // Dirección del despeje del portero.
        // --------------------------------------------------------------
        double ydisparo = 80;
        if (sj.getContrarioMasCerca(bola.x, bola.y) > 0) {
            ydisparo = -80;
        }

        int miJugadorMasCercano = sj.getMasCercanoDeBola();

        this.golpes[miJugadorMasCercano]++;

        if (miJugadorMasCercano == 0) {
            // --------------------------------------------------------------
            // Si mi jugador más cercano a la bola es el portero, éste sale
            // a despejar el balón.
            // --------------------------------------------------------------
            if (this.velocidadActual <= 15) {
                comandos.add(new ComandoIrA(0, bola.x, bola.y));
            } else {
                comandos.add(new ComandoIrA(0, bolaFutura.x, bolaFutura.y));
            }
            this.paseLargoHeuristico(0, sj, comandos);

        } else {

            double x = V3rgu1.REFERENCIA_PORTERO.x;
            double y = bolaFutura.getY();
            if (y < -25) {
                y = -20;
            }
            if (y > 25) {
                y = 20;
            }

            comandos.add(new ComandoIrA(0, x, y));
            this.paseLargoHeuristico(0, sj, comandos);

        }

    }//porterearBasico
    
    // ========================================================== //
    // ------------------------ Tools --------------------------- //
    // ========================================================== //

    /**
     * Cambia la tactica actual por una nueva.
     * 
     * @param int[][] tactica
     */
    private void cambiarTactica(int[][] tactica) {
        this.TACTICA_ACTUAL = tactica;
    }

    /**
     * Calcula la posible posición futura de la bola.
     * 
     * @param sj
     * @return
     */
    private Point posibleFuturaPosicionBola2(SituacionJugadores sj) {

        bolaFutura = new Point(0, 0);

        if (this.bolaAnterior != null) {

            double angulo = General.getAngulo(this.bolaAnterior.x, this.bolaAnterior.y, this.bola.x, this.bola.y);

            int numStop = 15;
            if (this.velocidadActual <= 15) {
                numStop = (int) (this.velocidadActual - 1);
            }

            int sumatorio = (int) this.sumatorio(this.velocidadActual, numStop);

            this.bolaFutura.x = (int) (Math.cos(angulo) * sumatorio) + this.bola.x;
            this.bolaFutura.y = (int) (Math.sin(angulo) * sumatorio) + this.bola.y;

        }

        return this.bolaFutura;

    }

    /**
     * Dispara a portería.
     * 
     * @param miJugador
     * @param sj
     * @param comandos
     */
    private void chutar(int miJugador, SituacionJugadores sj, Vector<Comando> comandos) {

        if (false && bola.x < 0) {
            this.despejar2(miJugador, sj, comandos);
        } else {
            int desvio = 0;
            if (sj.getMisJugadores()[miJugador].x > 30) {
                Point porterorival = sj.getContrario()[0];
                //int desvio = -porterorival.y;
                if (porterorival.y < 0) {
                    desvio = 20;
                } else {
                    desvio = -20;
                }
            }

            desvio = 0;

            //comandos.add(new ComandoGolpearBola(miJugador, 160, desvio));
            comandos.add(new ComandoTiroAPuerta(miJugador, desvio));

        }

    }//chutar    

    /**
     * Heurístico
     * 
     * @param miJugador
     * @param sj
     * @param comandos
     */
    private void despejar2(int miJugador, SituacionJugadores sj, Vector<Comando> comandos) {

        Point mejorZonaMuerta = null;
        double heuristicaMejorZonaMuerta = 0;

        Point[] misJugadores = sj.getMisJugadores();
        Point miJugadorPoint = misJugadores[miJugador];

        for (int i = 0; i < this.zonas.length; i++) {
            Point zonaPoint = this.zonas[i];

            double distanciaMinima = this.config.getPxDistanciaPaseLargo();

            if (zonaPoint.x > (miJugadorPoint.x + distanciaMinima) && (Math.abs(zonaPoint.y - miJugadorPoint.y) < 100)) {
                double heuristica =
                        this.heuristica(miJugadorPoint, zonaPoint, sj);

                if (heuristica > heuristicaMejorZonaMuerta) {
                    heuristicaMejorZonaMuerta = heuristica;
                    mejorZonaMuerta = zonaPoint;
                }
            }

        }

        if (mejorZonaMuerta != null) {
            comandos.add(new ComandoGolpearBola(miJugador, mejorZonaMuerta.x, mejorZonaMuerta.y));
        } else {
            this.chutar(miJugador, sj, comandos);
        }

    }//despejarHeuristico

    /**
     * Devuelve una lista con los índices de mis jugadores ordenador por
     * cercanía a la bola.
     *
     * @param SituacionJugadores sj
     * @return List mis jugadores ordenados por cercanía.
     */
    private List misJugadoresOrdenadosPorCercania(SituacionJugadores sj) {

        Map jugadores = new HashMap();
        Point[] points = sj.getMisJugadores();

        for (int i = 1; i < points.length; i++) {
            Point point = points[i];

            Point referenciaBola = bola;
            if (this.bolaFutura != null) {
                referenciaBola = this.bolaFutura;
            }

            double distancia = General.getDistancia(referenciaBola.x, referenciaBola.y, point.x, point.y);

            Double d = new Double(distancia);
            if (!jugadores.containsKey(d)) {
                jugadores.put(d, new Integer(i));
            } else {
                while (jugadores.containsKey(d)) {
                    int jug = ((Integer) jugadores.get(d)).intValue();
                    if (this.getVelocidad(i) > this.getVelocidad(jug)) {
                        //d = d - (this.getVelocidad(i) - this.getVelocidad(jug));
                        d = d - 0.0000000001;
                    } else {
                        d = d + 0.0000000001;
                    }
                }
            }

        }//for i

        List l = new ArrayList(jugadores.keySet());
        Collections.sort(l);

        List out = new ArrayList();
        for (int i = 0; i < l.size(); i++) {
            Double d = (Double) l.get(i);
            Integer j = (Integer) jugadores.get(d);
            out.add(j);
        }//for i

        return out;
    }

    /**
     * Comprueba si un jugador se encuentra dentro del área contraria.
     *
     * @param SituacionJugadores sj
     * @param int j
     * @return boolean
     */
    public boolean dentroDelAreaContraria(SituacionJugadores sj, int j) {
        Point jugador = sj.getMisJugadores()[j];
        return this.dentroDelAreaContraria(jugador);
    }

    /**
     * Comprueba si el punto "point" se encuentra dentro del área contraria.
     *
     * @return boolean
     */
    public boolean dentroDelAreaContraria(Point point) {
        return (point.x > 110 && Math.abs(point.y) < 70) ? true : false;
    }

    /**
     * Comprueba si un jugador se encuentra dentro de mi área.
     *
     * @param SituacionJugadores sj
     * @param int j
     * @return boolean
     */
    public boolean dentroDelAreaPropia(SituacionJugadores sj, int j) {
        Point jugador = sj.getMisJugadores()[j];
        return this.dentroDelAreaContraria(jugador);
    }

    /**
     * Comprueba si el punto "point" se encuentra dentro de mi área.
     *
     * @return boolean
     */
    public boolean dentroDelAreaPropria(Point point) {
        return (point.x < -110 && Math.abs(point.y) < 70) ? true : false;
    }

    /** 
     * Comprueba si alguno de mis jugadores tiene la bola,
     * en otras palabras, comprueba si el jugador más cercano es de mi equipo.
     * 
     * @return boolean
     */
    public boolean tengoLaBola(SituacionJugadores sj) {

        Point miJugadorMasCercanoALaBola = sj.getMisJugadores()[sj.getMasCercanoDeBola()];
        Point suJugadorMasCercanoALaBola = sj.getContrario()[sj.getContrarioMasCerca(bola.x, bola.y)];

        double miDistancia = General.getDistancia(bola.x, bola.y, miJugadorMasCercanoALaBola.x, miJugadorMasCercanoALaBola.y);

        double suDistancia = General.getDistancia(bola.x, bola.y, suJugadorMasCercanoALaBola.x, suJugadorMasCercanoALaBola.y);

        return (miDistancia < suDistancia);
    }

    /**
     * Comprueba si se puede golpear la bola.
     * Se puede golpear la bola siempre y cuando la velocidad de la bola sea menor que 15.
     * 
     * @param sj
     * @return TRUE si la velocidad de la bola es menor que 15.
     */
    private boolean sePuedeGolpearBola() {
        return (this.velocidadActual < 15) ? true : false;
    }


    private double sumatorio(double numero, double numStop) {
        double total = 0;
        double contador = numero;
        while (contador >= numStop) {
            total += contador;
            contador--;
        }
        return total;
    }

    private int sumatorio(int numero, int numStop) {
        int total = 0;
        int contador = numero;
        while (contador >= numStop) {
            total += contador;
            contador--;
        }
        return total;
    }

    /**
     * Devuelve una lista con los jugadores de mi equipo que se 
     * encuentran adelantados más allá de la línea del centro del campo.
     * 
     * @param sj
     * @return
     */
    private List<Integer> getMisDelanteros(SituacionJugadores sj) {
        Point[] misJugadores = sj.getMisJugadores();
        List<Integer> delanteros = new ArrayList();
        for (int i = 0; i < misJugadores.length; i++) {
            Point miJugador = misJugadores[i];
            if (miJugador.x < +25) {
                delanteros.add(new Integer(i));
            }
        }//for i
        return delanteros;
    }

    /**
     * Devuelve una lista con los jugadores del equipo contrario que se 
     * encuentran adelantados más allá de la línea del centro del campo.
     * 
     * @param sj
     * @return
     */
    private List<Integer> getSusDelanteros(SituacionJugadores sj) {
        Point[] contrarios = sj.getContrario();
        List delanteros = new ArrayList();
        for (int i = 0; i < contrarios.length; i++) {
            Point contrario = contrarios[i];
            if (contrario.x < 0) {
                delanteros.add(new Integer(i));
            }
        }//for i
        return delanteros;
    }

    /**
     * Gestiona todo el juego del equipo.
     * 
     * @param sj
     * @param comandos
     */
    private void jugar(SituacionJugadores sj, Vector<Comando> comandos) {

        double mvx = 0;
        double mvy = 0;

        Point bolaReferencia = this.bolaFutura;

        if (false) {
            // -----------------------------------------------        
            // Movimiento sobre la posición actual de la bola.
            // -----------------------------------------------
            mvx = (bola.x < 0) ? bola.x * 0.15 : bola.x * 0.15;
            mvy = bola.y * 0.10;
        } else {
            // -----------------------------------------------        
            // Movimiento sobre la posible posición futura de la bola.
            // -----------------------------------------------
            mvx = (bolaFutura.x < 0) ? bolaFutura.x * 0.15 : bolaFutura.x * 0.15;
            mvy = bolaFutura.y * 0.10;
        }

        int jugadoresPresionando = 1;
        if (bolaFutura.x > 35 && this.tengoLaBola(sj)) {
            jugadoresPresionando = 2;
        }

        int[] jugadoresColocados = new int[11];
        List jugadoresColocadosList = new ArrayList();
        int indiceColocados = 0;
        jugadoresColocados[indiceColocados] = 0;
        indiceColocados++;

        List<Integer> contrariosCubiertosList = new ArrayList();


        // ---------------------------------------------------------------------
        // PRESIÓN DE JUGADORES.
        // ---------------------------------------------------------------------
        // Recuperamos nuestros jugadores ordenados por cercanía a la bola.
        // ---------------------------------------------------------------------
        List js = this.misJugadoresOrdenadosPorCercania(sj);

        for (int i = 0; i < js.size() && i < jugadoresPresionando; i++) {
            int jugador = (Integer) js.get(i);
            Point jugadorPoint = sj.getMisJugadores()[jugador];

            if (jugador != 0) {

                if (i < jugadoresPresionando) {
                    comandos.add(new ComandoIrA(jugador, bolaFutura.x, bolaFutura.y));

                    if (Math.abs(General.getDistancia(bola.x, bola.y, jugadorPoint.x, jugadorPoint.y)) < 15) {
                        if (bolaReferencia.x > 0) {
                            this.chutar(jugador, sj, comandos);
                        } else {
                            this.paseLargoHeuristico(jugador, sj, comandos);
                        }
                    }

                    jugadoresColocados[indiceColocados] = jugador;
                    indiceColocados++;
                    jugadoresColocadosList.add(new Integer(jugador));
                }

            }
        }

        // ---------------------------------------------------------------------
        // DEFENSA AL HOMBRE.
        // ---------------------------------------------------------------------
        // Se cubre a todos los contrarios que se encuentren a partir de la
        // línea del centro del campo.
        // ---------------------------------------------------------------------
        List<Integer> susDelanteros = this.getSusDelanteros(sj);

        for (int i = 0; ((i < susDelanteros.size()) && (indiceColocados < 11)); i++) {
            int suDelantero = susDelanteros.get(i).intValue();
            Point suDelanteroPoint = sj.getContrario()[suDelantero];
            int[] info =
                    sj.getInfoMasCercano(sj.getMisJugadores(), suDelanteroPoint,
                    jugadoresColocados, false);

            int miDefensa = info[0];
            Point miDefensaPoint = sj.getMisJugadores()[miDefensa];
            jugadoresColocados[indiceColocados] = miDefensa;
            indiceColocados++;
            jugadoresColocadosList.add(new Integer(miDefensa));

            contrariosCubiertosList.add(suDelantero);

            double angulo =
                    General.getAngulo(suDelanteroPoint.x, suDelanteroPoint.y, bolaReferencia.x, bolaReferencia.y);
            int x = (int) (suDelanteroPoint.x + (this.config.getPxMarcajeDefensa() * Math.cos(angulo)));
            int y = (int) (suDelanteroPoint.y + (this.config.getPxMarcajeDefensa() * Math.sin(angulo)));

            comandos.add(new ComandoIrA(miDefensa, x, y));

            if (Math.abs(General.getDistancia(bola.x, bola.y, miDefensaPoint.x, miDefensaPoint.y)) < 15) {
                if (bolaReferencia.x > 0) {
                    this.chutar(miDefensa, sj, comandos);
                } else {
                    this.paseLargoHeuristico(miDefensa, sj, comandos);
                }
            }

        }//for i

        // ---------------------------------------------------------------------
        // DESMARQUE DE LOS DELANTEROS.
        // ---------------------------------------------------------------------
        List misDelanteros = this.getMisDelanteros(sj);

        for (int i = 0; ((i < misDelanteros.size()) && (indiceColocados < 11)); i++) {
            int miDelantero = ((Integer) misDelanteros.get(i)).intValue();
            int contrarioMasCercano = sj.getContrarioMasCerca(miDelantero);

            Point miDelanteroPoint = sj.getMisJugadores()[miDelantero];
            Point contrarioPoint = sj.getContrario()[contrarioMasCercano];

            if (!jugadoresColocadosList.contains(miDelantero)) {

                // Si el defensa me está intentando cubrir, me pongo delante de él.
                if (Math.abs(General.getDistancia(miDelanteroPoint.x, miDelanteroPoint.y, contrarioPoint.x, contrarioPoint.y)) < 10) {

                    double angulo =
                            General.getAngulo(contrarioPoint.x, contrarioPoint.y, bola.x, bola.y);
                    int x = (int) (miDelanteroPoint.x - (this.config.getPxMarcajeAtaque() * Math.cos(angulo)));
                    int y = (int) (miDelanteroPoint.y - (this.config.getPxMarcajeAtaque() * Math.sin(angulo)));

                    comandos.add(new ComandoIrA(miDelantero, x, y));
                }

                if (bolaReferencia.x > 0) {
                    this.chutar(miDelantero, sj, comandos);
                } else {
                    this.paseLargoHeuristico(i, sj, comandos);
                }

            }

        }//for i

        // ---------------------------------------------------------------------
        // DESMARQUE DE LOS JUGADORES AÚN NO COLOCADOS.
        // ---------------------------------------------------------------------

        for (int i = 0; ((i < 11) && (indiceColocados < 11)); i++) {

            Point miDelanteroPoint = sj.getMisJugadores()[i];

            int contrarioMasCercano = sj.getContrarioMasCerca(i);
            Point contrarioPoint = sj.getContrario()[contrarioMasCercano];

            if (contrariosCubiertosList.contains(new Integer(contrarioMasCercano))) {
                continue;
            }

            if (!jugadoresColocadosList.contains(new Integer(i))) {

                // Si el defensa me está intentando cubrir, me pongo delante de él.
                if (Math.abs(General.getDistancia(miDelanteroPoint.x, miDelanteroPoint.y, contrarioPoint.x, contrarioPoint.y)) < 25) {

                    double angulo =
                            General.getAngulo(contrarioPoint.x, contrarioPoint.y, bolaReferencia.x, bolaReferencia.y);
                    int x = (int) (contrarioPoint.x + (this.config.getPxMarcajeAtaque() * Math.cos(angulo)));
                    int y = (int) (contrarioPoint.y + (this.config.getPxMarcajeAtaque() * Math.sin(angulo)));

                    jugadoresColocados[indiceColocados] = i;
                    indiceColocados++;
                    jugadoresColocadosList.add(new Integer(i));

                    contrariosCubiertosList.add(new Integer(contrarioMasCercano));

                    comandos.add(new ComandoIrA(i, x, y));

                    if (bolaReferencia.x > 0) {
                        this.chutar(i, sj, comandos);
                    } else {
                        this.paseLargoHeuristico(i, sj, comandos);
                    }
                }

            }

        }//for i

        // ---------------------------------------------------------------------
        // JUEGO - MOVIMIENTOS EN EQUIPO.
        // ---------------------------------------------------------------------

        for (int i = 0; i < js.size() && (indiceColocados < 11); i++) {
            int jugador = (Integer) js.get(i);
            Point jugadorPoint = sj.getMisJugadores()[jugador];
            if (!jugadoresColocadosList.contains(jugador)) {
                comandos.add(new ComandoIrA(jugador, this.TACTICA_ACTUAL[jugador][0] + mvx, this.TACTICA_ACTUAL[jugador][1] + mvy));

                if (Math.abs(General.getDistancia(bola.x, bola.y, jugadorPoint.x, jugadorPoint.y)) < 15) {
                    //if (sj.getMisJugadores()[jugador].x > 0) {
                    if (bolaReferencia.x > 0) {
                        this.chutar(jugador, sj, comandos);
                    } else {
                        this.paseLargoHeuristico(jugador, sj, comandos);
                    }
                }

                jugadoresColocados[indiceColocados] = jugador;
                indiceColocados++;
                jugadoresColocadosList.add(new Integer(jugador));
            }
        }//for i

    }

    /**
     * Ejecuta por parte del jugador miJugador, un pago comprobando el jugador
     * mejor posicionado.
     * 
     * @param miJugador
     * @param sj
     * @param comandos
     */
    private void paseLargoHeuristico(int miJugador, SituacionJugadores sj, Vector<Comando> comandos) {

        int jugadorMejorColocado = 0;
        double heuristicaJugadorMejorColocado = 0;

        List<Point> misJugadoresAdelantados = new ArrayList();

        Point[] misJugadores = sj.getMisJugadores();
        Point miJugadorPoint = misJugadores[miJugador];

        for (int i = 0; i < misJugadores.length; i++) {

            Point jugadorPoint = misJugadores[i];
            if (jugadorPoint.x > miJugadorPoint.x) {
                misJugadoresAdelantados.add(jugadorPoint);

                double distanciaMinima = this.config.getPxDistanciaPaseLargo();

                if (jugadorPoint.x > (miJugadorPoint.x + distanciaMinima)) {
                    double heuristica =
                            this.heuristica(jugadorPoint, miJugadorPoint, sj);

                    if (heuristica > heuristicaJugadorMejorColocado) {
                        heuristicaJugadorMejorColocado = heuristica;
                        jugadorMejorColocado = i;
                    }
                }
            }

        }//for i

        if (jugadorMejorColocado == 0 || heuristicaJugadorMejorColocado < 5) {
            this.despejar2(miJugador, sj, comandos);
        } else {
            comandos.add(new ComandoPase(miJugador, jugadorMejorColocado));
        }

    }//paseLargoHeuristico
    
    /**
     * Comprueba la heurística entre 2 puntos.
     * 
     * @param a
     * @param b
     * @param sj
     * @return
     */
    private double heuristica(Point a, Point b, SituacionJugadores sj) {

        double distanciaMinima = 160;

        double angulo =
                General.getAngulo(a.x, a.y, b.x, b.y);

        double m = 0;
        while (m < 100) {
            int x = (int) (a.x + (m * Math.cos(angulo)));
            int y = (int) (a.y + (m * Math.sin(angulo)));
            m += 20;

            int contrarioMasCercano =
                    sj.getContrarioMasCerca(x, y);
            Point contrarioMasCercanoPoint =
                    sj.getContrario()[contrarioMasCercano];

            double distancia =
                    General.getDistancia(x, y, contrarioMasCercanoPoint.x, contrarioMasCercanoPoint.y);

            if (distancia < distanciaMinima) {
                distanciaMinima = distancia;
            }

        }

        return distanciaMinima;

    }//heuristica
    
}//V3rgu1